package com.xx.eshop.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class UploadUtils {

	private static final int BUFFER_LEN = 1024;

	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
			'e', 'f' };

	/**
	 * 求某个字符串的md5签名结果
	 * 
	 * @param str
	 *            原始字符串
	 * @return md5结果
	 */
	public static String toMD5(String str) {
		try {
			MessageDigest md5 = MessageDigest.getInstance("md5");
			return new String(toHex(md5.digest(str.getBytes()), DIGITS_LOWER));
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 生成某一个输入流的md5签名结果
	 * 
	 * @param is
	 * @return
	 */
	public static String getMD5NameOnly(InputStream is) {
		try {
			// 获得签名算法对象
			MessageDigest md5 = MessageDigest.getInstance("md5");
			// 从输出流获取循环读取字节
			final byte[] buffer = new byte[BUFFER_LEN];
			int read = is.read(buffer, 0, BUFFER_LEN);
			while (read > -1) {
				// 签名算法对象更新结果
				md5.update(buffer, 0, read);
				read = is.read(buffer, 0, BUFFER_LEN);
			}
			String filename = new String(toHex(md5.digest(), DIGITS_LOWER));
			return filename;
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
		}
	}
	
	/**
	 * 求文件的扩展名   1.txt    ==> .txt
	 * @param filename
	 * @return
	 */
	public static String getExt(String filename) {
		return filename.substring(filename.lastIndexOf("."));
	}

	/**
	 * 
	 * @param is
	 *            输入流
	 * @param dir
	 *            输出目录
	 * @param ext
	 *            输出文件后缀
	 */
	public static String saveWithMD5Name(InputStream is, String dir, String ext) {
		return saveWithMD5Name(is, dir, ext, 0);
	}

	/**
	 * 
	 * @param is
	 *            输入流
	 * @param dir
	 *            输出目录
	 * @param ext
	 *            输出文件后缀
	 * @param level
	 *            代表子文件夹的层数
	 */
	public static String saveWithMD5Name(InputStream is, String dir, String ext, int level) {
		FileOutputStream os = null;
		String dist = null;
		File dirfile = new File(dir);
		if (!dirfile.exists()) {
			dirfile.mkdirs();
		}
		String src = dir + UUID.randomUUID().toString();
		String imageurl = null;
		try {
			os = new FileOutputStream(src);
			// 获得签名算法对象
			MessageDigest md5 = MessageDigest.getInstance("md5");

			// 从输出流获取循环读取字节
			final byte[] buffer = new byte[BUFFER_LEN];
			int read = is.read(buffer, 0, BUFFER_LEN);
			while (read > -1) {
				// 签名算法对象更新结果
				md5.update(buffer, 0, read);
				// 同时写出到输出流
				os.write(buffer, 0, read);
				read = is.read(buffer, 0, BUFFER_LEN);
			}
			String filename = new String(toHex(md5.digest(), DIGITS_LOWER));
			String subdir = "";
			for (int i = 0; i < level; i++) {
				subdir += filename.charAt(i) + File.separator; // "\" "/"
			}
			File subdirfile = new File(dir + subdir);
			if (!subdirfile.exists()) {
				subdirfile.mkdirs();// 创建多级文件夹
			}
			dist = dir + subdir + filename + ext;
			imageurl = subdir + filename + ext;
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
				}
			}
		}

		// jdk 7
		try {
			Files.move(new File(src).toPath(), new File(dist).toPath(), StandardCopyOption.REPLACE_EXISTING);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return imageurl;

		// new File(src).renameTo(new File(dist)); // 重命名文件
	}

	private static char[] toHex(final byte[] data, final char[] toDigits) {
		final int l = data.length;
		final char[] out = new char[l << 1];
		// two characters form the hex value.
		for (int i = 0, j = 0; i < l; i++) {
			out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
			out[j++] = toDigits[0x0F & data[i]];
		}
		return out;
	}

	public static void main(String[] args) {
		InputStream stream = new ByteArrayInputStream("123".getBytes());
		saveWithMD5Name(stream, "e:\\", ".txt", 6);
		System.out.println(toMD5("123"));
	}

	public static void is2os(InputStream is, OutputStream os) {
		try {
			byte[] buf = new byte[1024 * 16];
			int len = -1;
			while (true) {
				len = is.read(buf);
				if (len == -1) {
					break;
				}
				os.write(buf, 0, len);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
				}
			}
		}
	}

}
